// api/request.js
// 封装 uni.request，自动加 token 和 Token 管理

// 基础URL - 电脑局域网IP地址，用于手机访问电脑后端
// 使用无线局域网(WLAN)的IP地址
export const BASE_URL = 'http://10.34.93.196:8080'; // 已更新为电脑实际的无线局域网IP地址

// Token 相关常量
const TOKEN_KEY = 'token';
const REFRESH_TOKEN_KEY = 'refreshToken';
const TOKEN_EXPIRE_TIME_KEY = 'tokenExpireTime';

// 是否正在刷新Token
let isRefreshing = false;
// 等待刷新的请求队列
let refreshSubscribers = [];

/**
 * 存储Token信息
 * @param {Object} tokenInfo - Token信息对象
 */
export function saveTokenInfo(tokenInfo) {
  if (tokenInfo) {
    // 保存Token
    if (tokenInfo.token) {
      uni.setStorageSync(TOKEN_KEY, tokenInfo.token);
    }
    // 保存刷新Token
    if (tokenInfo.refreshToken) {
      uni.setStorageSync(REFRESH_TOKEN_KEY, tokenInfo.refreshToken);
    }
    // 计算并保存过期时间（假设返回的是过期时间戳或有效期秒数）
    if (tokenInfo.expireTime) {
      uni.setStorageSync(TOKEN_EXPIRE_TIME_KEY, tokenInfo.expireTime);
    } else if (tokenInfo.expiresIn) {
      const expireTime = Date.now() + tokenInfo.expiresIn * 1000;
      uni.setStorageSync(TOKEN_EXPIRE_TIME_KEY, expireTime);
    }
  }
}

/**
 * 获取Token
 * @returns {string|null} Token字符串或null
 */
export function getToken() {
  return uni.getStorageSync(TOKEN_KEY);
}

/**
 * 获取刷新Token
 * @returns {string|null} 刷新Token字符串或null
 */
export function getRefreshToken() {
  return uni.getStorageSync(REFRESH_TOKEN_KEY);
}

/**
 * 清除Token信息
 */
export function clearTokenInfo() {
  uni.removeStorageSync(TOKEN_KEY);
  uni.removeStorageSync(REFRESH_TOKEN_KEY);
  uni.removeStorageSync(TOKEN_EXPIRE_TIME_KEY);
}

/**
 * 检查Token是否过期
 * @returns {boolean} 是否已过期
 */
export function isTokenExpired() {
  const expireTime = uni.getStorageSync(TOKEN_EXPIRE_TIME_KEY);
  if (!expireTime) return true;
  return Date.now() >= expireTime;
}

/**
 * 刷新Token
 * @returns {Promise}
 */
function refreshToken() {
  const refreshToken = getRefreshToken();
  if (!refreshToken) {
    return Promise.reject(new Error('没有刷新Token'));
  }

  return new Promise((resolve, reject) => {
    uni.request({
      url: `${BASE_URL}/auth/refresh-token`,
      method: 'POST',
      header: {
        'Content-Type': 'application/json'
      },
      data: {
        token: refreshToken
      },
      success: (res) => {
        if (res.statusCode === 200 && res.data && res.data.data && res.data.data.token) {
          // 后端返回格式可能是 {data: {token: '...', tokenType: '...'}} 或直接是 {token: '...'}
          const tokenData = res.data.data || res.data;
          saveTokenInfo({
            token: tokenData.token,
            tokenType: tokenData.tokenType
          });
          resolve(tokenData.token);
          // 通知所有等待的请求
          refreshSubscribers.forEach(callback => callback(tokenData.token));
          refreshSubscribers = [];
        } else {
          // 刷新失败，清除Token
          clearTokenInfo();
          reject(new Error('刷新Token失败'));
        }
      },
      fail: (err) => {
        clearTokenInfo();
        reject(err);
      },
      complete: () => {
        isRefreshing = false;
      }
    });
  });
}

/**
 * 订阅Token刷新
 * @param {Function} callback - 刷新后的回调函数
 */
function subscribeTokenRefresh(callback) {
  refreshSubscribers.push(callback);
}

/**
 * 检查是否为不需要Token的接口
 * @param {string} url - 请求URL
 * @returns {boolean} 是否不需要Token
 */
function isNoTokenRequired(url) {
  // 登录注册相关接口不需要Token
  const noTokenPaths = [
    '/auth/login', // 用户登录
    '/auth/register', // 用户注册
    '/auth/refresh-token', // 刷新Token
    '/api/auth/sms/send', // 发送验证码
    '/api/auth/sms/verify', // 验证验证码
    '/api/auth/password/reset' // 重置密码
  ];
  
  // 添加调试日志
  console.log('检查URL是否需要token:', url);
  const result = noTokenPaths.some(path => url.includes(path));
  console.log('检查结果:', result);
  return result;
}

/**
 * 发送请求
 * @param {string} url - 请求URL
 * @param {Object} options - 请求选项
 * @returns {Promise}
 */
export function request(url, options = {}) {
  // 确保options存在并有默认值
  options = options || {};
  options.header = options.header || {};
  
  // 处理基础URL
  const requestUrl = url.startsWith('http') ? url : BASE_URL + url;
  
  return new Promise((resolve, reject) => {
    // 检查是否为不需要Token的接口
    const noTokenRequired = isNoTokenRequired(url);
    
    // 获取Token，但对不需要Token的接口不进行Token验证和刷新
    let token = noTokenRequired ? null : getToken();
    console.log('请求URL:', url, '是否需要token:', !noTokenRequired, '当前token存在:', !!token);
    
    // 获取刷新Token
    const refreshTokenStr = getRefreshToken();
    console.log('刷新Token存在:', !!refreshTokenStr);
    
    // 如果Token已过期且有刷新Token，先刷新Token
    if (token && isTokenExpired() && refreshTokenStr) {
      if (!isRefreshing) {
        isRefreshing = true;
        refreshToken().then(newToken => {
          token = newToken;
          doRequest(requestUrl, options, token, resolve, reject);
        }).catch(err => {
          // 刷新失败，记录错误但不立即跳转到登录页
          console.error('Token刷新失败:', err);
          // 仍然尝试使用现有token发送请求，让后端返回具体错误
          doRequest(requestUrl, options, token, resolve, reject);
        }).finally(() => {
          isRefreshing = false;
        });
      } else {
        // 如果正在刷新，等待刷新完成
        subscribeTokenRefresh(newToken => {
          token = newToken;
          doRequest(requestUrl, options, token, resolve, reject);
        });
      }
    } else {
      // 正常请求
      doRequest(requestUrl, options, token, resolve, reject);
    }
  });
}

/**
 * 执行实际的请求
 * @param {string} url - 请求URL
 * @param {Object} options - 请求选项
 * @param {string} token - Token
 * @param {Function} resolve - resolve函数
 * @param {Function} reject - reject函数
 */
function doRequest(url, options, token, resolve, reject) {
  // 确保options.header存在
  options.header = options.header || {};
  
  // 为GET请求单独处理参数，确保参数正确传递
  let requestUrl = url;
  let requestOptions = { ...options };
  
  // 重要：为所有需要token的接口添加Authorization头
  if (token) {
    // 先去除可能存在的双引号
    let cleanToken = token.replace(/"/g, '');
    // 去除可能存在的Bearer前缀（不区分大小写）
    cleanToken = cleanToken.replace(/^bearer\s+/i, '');
    // 设置正确格式的Authorization头
    requestOptions.header['Authorization'] = `Bearer ${cleanToken}`;
    console.log('已添加Authorization头，token长度:', cleanToken.length, '原始token:', token);
  } else {
    console.log('未添加Authorization头，token不存在');
  }
  
  // 只对非GET请求设置Content-Type，GET请求不需要
  if (requestOptions.method && requestOptions.method !== 'GET' && !requestOptions.header['Content-Type']) {
    requestOptions.header['Content-Type'] = 'application/json';
  }
  
  // 为GET请求参数添加URL拼接，确保参数被正确传递到后端
  if ((requestOptions.method || 'GET') === 'GET' && requestOptions.params) {
    console.log('GET请求参数详情:', JSON.stringify(requestOptions.params));
    console.log('user参数是否存在:', 'user' in requestOptions.params ? `是，值为: ${requestOptions.params.user}` : '否');
    
    // 构建查询字符串
    const queryParams = [];
    for (const key in requestOptions.params) {
      if (requestOptions.params.hasOwnProperty(key)) {
        const value = requestOptions.params[key];
        // 只添加非undefined和非null的值
        if (value !== undefined && value !== null) {
          queryParams.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
        }
      }
    }
    
    // 将查询参数拼接到URL
    if (queryParams.length > 0) {
      const separator = url.includes('?') ? '&' : '?';
      requestUrl += separator + queryParams.join('&');
      console.log('GET请求最终URL:', requestUrl);
      
      // 注意：由于我们已经将参数拼接到URL，这里不再需要params对象
      // 但为了保持与uni.request的兼容性，我们保留params对象
    }
  }
  
  // 发送请求前的完整日志
  console.log(`即将发送到: ${requestUrl}`);
  console.log('请求方法:', requestOptions.method || 'GET');
  console.log('请求头:', requestOptions.header);
  console.log('请求参数:', requestOptions.params || requestOptions.data || {});
  
  // 直接使用uni.request，确保params参数被正确处理
  uni.request({
    url: requestUrl,
    ...requestOptions,
    success: (res) => {
      console.log('请求成功，状态码:', res.statusCode, '响应数据:', res.data);
      handleResponse(res, resolve, reject);
    },
    fail: (err) => {
      console.error('请求失败:', err);
      console.error('请求失败详情:', JSON.stringify(err));
      // 网络错误处理
      if (err.errMsg && err.errMsg.includes('request:fail')) {
        showError('网络连接失败，请检查网络设置');
      }
      reject(err);
    }
  });
}

/**
 * 处理响应
 * @param {Object} res - 响应对象
 * @param {Function} resolve - resolve函数
 * @param {Function} reject - reject函数
 */
function handleResponse(res, resolve, reject) {
  // 统一处理响应码
  if (res.statusCode === 401) {
    // Token过期或无效
    clearTokenInfo();
    goToLogin();
    reject(new Error('登录已过期，请重新登录'));
  } else if (res.statusCode === 403) {
    // 没有权限
    showError('没有权限执行此操作');
    reject(new Error('没有权限'));
  } else if (res.statusCode >= 200 && res.statusCode < 300) {
    // 请求成功，但还需要检查业务逻辑状态码
    const responseData = res.data;
    // 如果响应数据包含code字段，并且code不为1，则表示业务逻辑失败
    if (responseData && responseData.hasOwnProperty('code') && responseData.code !== 1) {
      const errorMsg = responseData.msg || '业务逻辑处理失败';
      // 不显示错误提示，让调用方自己处理
      reject(new Error(errorMsg));
    } else {
      // 正常成功的响应
      resolve(responseData);
    }
  } else {
    // 其他错误
    const errorMsg = res.data?.message || res.data?.error || `请求失败(${res.statusCode})`;
    showError(errorMsg);
    reject(new Error(errorMsg));
  }
}

/**
 * 跳转到登录页
 */
function goToLogin() {
  // 避免重复跳转
  const currentPages = getCurrentPages();
  const currentRoute = currentPages[currentPages.length - 1]?.route;
  if (currentRoute !== 'pages/login/login') {
    uni.removeStorageSync('token');
    uni.redirectTo({ 
      url: '/pages/login/login',
      fail: () => {
        // 如果redirectTo失败，使用reLaunch
        uni.reLaunch({ url: '/pages/login/login' });
      }
    });
  }
}

/**
 * 显示错误提示
 * @param {string} message - 错误信息
 */
function showError(message) {
  // 详细记录错误信息用于调试
  //console.error('错误信息详情:', message);
  //console.error('错误发生时间:', new Date().toLocaleString());
  
  // 检查网络相关的错误关键词
  if (message && (message.includes('request:fail') || message.includes('timeout'))) {
    console.error('可能的原因分析:');
    console.error('1. 后端服务未启动');
    console.error('2. IP地址或端口配置错误');
    console.error('3. 手机和电脑不在同一网络');
    console.error('4. 防火墙阻止了连接');
    console.error('请参考docs/backend_connection_guide.md文档进行配置');
  }
  
  // 可以根据需要自定义错误提示方式
  uni.showToast({
    title: message,
    icon: 'none',
    duration: 3000
  });
}

// 导出常用的HTTP方法
export function get(url, params = {}) {
  // 添加详细调试日志
  console.log('【GET请求】开始准备，URL:', url);
  console.log('【GET请求】参数对象:', params);
  console.log('【GET请求】参数类型:', typeof params);
  console.log('【GET请求】参数属性:', Object.keys(params || {}));
  
  // 特别检查conversation_id参数
  if (params.conversation_id) {
    console.log('【GET请求】检测到conversation_id参数:', params.conversation_id);
    console.log('【GET请求】conversation_id类型:', typeof params.conversation_id);
  } else {
    console.warn('【GET请求】未检测到conversation_id参数');
  }
  
  // 调用request函数并添加链式调试
  const requestPromise = request(url, {
    method: 'GET',
    params: params  // 使用params而不是data，确保GET请求参数正确附加
  });
  
  // 添加Promise链调试
  return requestPromise.then(response => {
    console.log('【GET请求】成功完成，URL:', url);
    console.log('【GET请求】响应状态:', response?.status || '未知');
    return response;
  }).catch(error => {
//    console.error('【GET请求】执行失败，URL:', url);
   // console.error('【GET请求】失败原因:', error?.message || error);
    throw error; // 重新抛出错误以保持原始行为
  });
}

export function post(url, data = {}) {
  return request(url, {
    method: 'POST',
    data: data
  });
}

export function put(url, data = {}) {
  return request(url, {
    method: 'PUT',
    data: data
  });
}

export function del(url, data = {}) {
  return request(url, {
    method: 'DELETE',
    data: data
  });
}

// 导出上传文件方法
export function upload(url, filePath, options = {}) {
  return new Promise((resolve, reject) => {
    const token = getToken();
    const uploadOptions = {
      url: url.startsWith('http') ? url : BASE_URL + url,
      filePath,
      name: 'file',
      header: {
        ...options.header,
        'Authorization': token ? `Bearer ${token}` : ''
      },
      formData: options.formData || {},
      success: (res) => {
        try {
          const data = typeof res.data === 'string' ? JSON.parse(res.data) : res.data;
          if (res.statusCode >= 200 && res.statusCode < 300) {
            resolve(data);
          } else {
            reject(new Error(data.message || '上传失败'));
          }
        } catch (e) {
          reject(new Error('上传失败'));
        }
      },
      fail: reject
    };
    
    uni.uploadFile(uploadOptions);
  });
}

// 导出下载文件方法
export function download(url, options = {}) {
  return new Promise((resolve, reject) => {
    const token = getToken();
    const downloadOptions = {
      url: url.startsWith('http') ? url : BASE_URL + url,
      header: {
        ...options.header,
        'Authorization': token ? `Bearer ${token}` : ''
      },
      success: resolve,
      fail: reject
    };
    
    uni.downloadFile(downloadOptions);
  });
}